import React, { useEffect, useRef } from "react";
import { OrbitControls } from "@three-ts/orbit-controls";
import * as THREE from "three";
type Props = {};

const A = (props: Props) => {
  const myref = useRef<any>(null);
  const _thre: any = THREE;
  useEffect(() => {
    let innerWidth = window.innerWidth;
    let innerHeight = window.innerHeight;
    // 场景
    let scene = new _thre.Scene();
    scene.background = new _thre.Color(0x160016);
    // 透视相机
    let camera = new _thre.PerspectiveCamera(
      60,
      innerWidth / innerHeight,
      1,
      1000
    );
    camera.position.set(0, 4, 21);
    // WebGL渲染器常量
    let renderer = new _thre.WebGLRenderer();
    renderer.setSize(innerWidth, innerHeight);
    //添加到页面中
    myref.current.appendChild(renderer.domElement);
    //大小
    window.addEventListener("resize", (event) => {
      camera.aspect = innerWidth / innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(innerWidth, innerHeight);
    });
    // 轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.enablePan = false;

    let gu = {
      time: { value: 0 },
    };

    let sizes: any[] = [];
    let shift: any[] = [];
    let pushShift = () => {
      shift.push(
        Math.random() * Math.PI,
        Math.random() * Math.PI * 2,
        (Math.random() * 0.9 + 0.1) * Math.PI * 0.1,
        Math.random() * 0.9 + 0.1
      );
    };
    //内圈的数量
    let pts = new Array(50000).fill(sizes).map((p) => {
      sizes.push(Math.random() * 1.5 + 0.5);
      pushShift();
      return new _thre.Vector3()
        .randomDirection()
        .multiplyScalar(Math.random() * 0.5 + 9.5);
    });
    //外圈的数量
    for (let i = 0; i < 100000; i++) {
      let r = 10,
        R = 40;
      let rand = Math.pow(Math.random(), 1.5);
      let radius = Math.sqrt(R * R * rand + (1 - rand) * r * r);
      pts.push(
        new _thre.Vector3().setFromCylindricalCoords(
          radius,
          Math.random() * 2 * Math.PI,
          (Math.random() - 0.5) * 2
        )
      );
      sizes.push(Math.random() * 1.5 + 0.5);
      pushShift();
    }

    let g = new _thre.BufferGeometry().setFromPoints(pts);
    g.setAttribute("sizes", new _thre.Float32BufferAttribute(sizes, 1));
    g.setAttribute("shift", new _thre.Float32BufferAttribute(shift, 4));
    let m = new _thre.PointsMaterial({
      size: 0.125,
      transparent: true,
      depthTest: false,
      blending: _thre.AdditiveBlending,
      onBeforeCompile: (shader: {
        uniforms: { time: { value: number } };
        vertexShader: string;
        fragmentShader: string;
      }) => {
        shader.uniforms.time = gu.time;
        shader.vertexShader = `
                  uniform float time;
                  attribute float sizes;
                  attribute vec4 shift;
                  varying vec3 vColor;
                  ${shader.vertexShader}
                `
          .replace(`gl_PointSize = size;`, `gl_PointSize = size * sizes;`)
          .replace(
            `#include <color_vertex>`,
            `#include <color_vertex>
                    float d = length(abs(position) / vec3(40., 10., 40));
                    d = clamp(d, 0., 1.);
                    vColor = mix(vec3(227., 155., 0.), vec3(100., 50., 255.), d) / 255.;
                  `
          )
          .replace(
            `#include <begin_vertex>`,
            `#include <begin_vertex>
                    float t = time;
                    float moveT = mod(shift.x + shift.z * t, PI2);
                    float moveS = mod(shift.y + shift.z * t, PI2);
                    transformed += vec3(cos(moveS) * sin(moveT), cos(moveT), sin(moveS) * sin(moveT)) * shift.w;
                  `
          );
        //console.log(shader.vertexShader);
        shader.fragmentShader = `
                  varying vec3 vColor;
                  ${shader.fragmentShader}
                `
          .replace(
            `#include <clipping_planes_fragment>`,
            `#include <clipping_planes_fragment>
                    float d = length(gl_PointCoord.xy - 0.5);
                    //if (d > 0.5) discard;
                  `
          )
          .replace(
            `vec4 diffuseColor = vec4( diffuse, opacity );`,
            `vec4 diffuseColor = vec4( vColor, smoothstep(0.5, 0.1, d)/* * 0.5 + 0.5*/ );`
          );
        //console.log(shader.fragmentShader);
      },
    });
    let p = new _thre.Points(g, m);
    p.rotation.order = "ZYX";
    p.rotation.z = 0.2;
    scene.add(p);

    let clock = new _thre.Clock();

    renderer.setAnimationLoop(() => {
      controls.update();
      let t = clock.getElapsedTime() * 0.5;
      gu.time.value = t * Math.PI;
      p.rotation.y = t * 0.05;
      renderer.render(scene, camera);
    });
  }, []);
  return <div className="myThree" ref={myref}></div>;
};

export default A;
